-
Notifications
You must be signed in to change notification settings - Fork 118
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix HTTP2StreamChannel leak #657
Fix HTTP2StreamChannel leak #657
Conversation
@@ -241,7 +241,7 @@ final class HTTP2Connection { | |||
// before. | |||
let box = ChannelBox(channel) | |||
self.openStreams.insert(box) | |||
self.channel.closeFuture.whenComplete { _ in | |||
channel.closeFuture.whenComplete { _ in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the actual bug fix. However I have no idea how to test it!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have run into this just today. If we send a too large header and the server sends a go away frame the child channel is closed but the parent channel not. This might be a good way to test this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can try to test this by triggering the shutdown event and finding which channels get sent this user event. So long as we can hook the parent channel we should observe that it doesn't see it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The question is: How do I get access to the stream/child channel? All the ideas I had so far a quite locked down. Of course I can add an internal function that gives me the currently active channels.
func forTestingGetActiveChildChannels -> EventLoopFuture<[Channel]>
wdyt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think adding a testing function is fine. You can guard it behind an SPI, which is probably sufficient.
b8e3bad
to
bfb149c
Compare
promise.futureResult.whenComplete { _ in | ||
// Once we have written the last message we must close the http2 stream, since this | ||
// break a reference cycle in HTTP2Connection. | ||
context.close(promise: nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a little surprised that this is necessary. swift-nio-http2 should notify you that the stream is closed when both sides have sent their .end
. Are you entirely confident this is required?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not. I was only testing the child channel. And wanted to be as defensive as possible. Do you want me to remove it again?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think we shouldn't add code that we don't really need.
@@ -241,7 +241,7 @@ final class HTTP2Connection { | |||
// before. | |||
let box = ChannelBox(channel) | |||
self.openStreams.insert(box) | |||
self.channel.closeFuture.whenComplete { _ in | |||
channel.closeFuture.whenComplete { _ in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can try to test this by triggering the shutdown event and finding which channels get sent this user event. So long as we can hook the parent channel we should observe that it doesn't see it.
03f4234
to
0ddba75
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good modulo a couple of nits.
Sources/AsyncHTTPClient/ConnectionPool/HTTP2/HTTP2ClientRequestHandler.swift
Show resolved
Hide resolved
Sources/AsyncHTTPClient/ConnectionPool/HTTP2/HTTP2ClientRequestHandler.swift
Show resolved
Hide resolved
0ddba75
to
707eef1
Compare
@glbrntt added/updated code comments to point out the http/1.1 semantics of the action |
We leak
HTTP2StreamChannel
s in long living HTTPClients. The reason for this is that we registered the callback to remove anHTTP2StreamChannel
from the openStreams set in HTTP2Connection on the HTTP2 connection channel and not on theHTTP2StreamChannel
itself. (Side note:self.channel
vs localvar channel
is always crazy dangerous)Changes
self.
)HTTP2StreamChannel
when the request has finished